Dernièrement, dans une application ReactJS, j’ai été confronté à la mise en place d’un bouton qui permet de faire défiler une page jusqu’en haut. Dans le même temps, j’avais découvert Hooks, une des nouvelles fonctionnalités proposées par le framework.
Je me suis donc lancé. J’ai préparé une page HTML potentiellement assez longue pour qu’elle nécessite l’utilisation de ce type de bouton (div.conteneur). Et j’ai placé une div destinée à accueillir mon fameux bouton (div#scrollToTop).
<div class="conteneur">
<div class="item item-1">
</div>
<div class="item item-2">
</div>
<div class="item item-3">
</div>
<div class="item item-4">
</div>
</div>
<div id="scrollToTop"></div>
J’ai ajouté une touche de CSS pour m’assurer de la suffisante longueur de la page et pour positionner mon bouton en bas à droite, à 10px des bords.
.conteneur {
display: flex;
flex-direction: column;
}
.item {
min-height: 100vh;
}
.item-1 {
background: repeating-linear-gradient(42deg, #375A7D, #6E5A7D 30px);
}
.item-2 {
background: repeating-linear-gradient(45deg, #C36E82, #F57382 30px);
}
.item-3 {
background: repeating-linear-gradient(45deg, #FAB496, #375A7D 30px);
}
.item-4 {
background: repeating-linear-gradient(45deg, #375A7D, #6E5A7D 30px);
}
.scrollToTop {
position:fixed;
bottom:10px;
right:10px;
}
Ensuite, il a fallu s’attaquer au codage du composant :
const ScrollToTop = ({ scrollStepInPx, delayInMs }) => {
...
return (
<button className="btn btn-secondary scrollToTop" onClick=...>
<span className="glyphicon glyphicon-chevron-up"/>
</button)
}
Au lieu d’utiliser un class component, je suis resté sur un fonctionnal component et j’ai fait le choix de gérer son state à l’aide de l’API useState proposée avec Hook, la nouvelle fonctionnalité de ReactJS :
const [scroll, setScroll] = React.useState(false);
Le state « scroll » permet de savoir si un scroll est en cours
La méthode « setScroll » permet de modifier cet état,
donc le rendu de ce composant,
donc l’exécution ou non du scroll.
J’ai ajouté la fonction chargée du scroll :
const scrollStep = () => {
if (window.pageYOffset === 0) {
clearInterval(intervalId);
setScroll(false);
}
window.scroll(0, window.pageYOffset - scrollStepInPx);
};
Lorsque le scroll est terminé (window.pageYOffset === 0),
clearInterval interrompt la répétition de cette fonction
et la méthode setScroll repasse le state à false.
Cela entraîne un nouveau rendu du composant, sans exécution du scroll.
Au moment du rendu, selon le state, il faut lancer ou non la répétition de l’appel au scroll (scrollStep) et stocker l’identifiant correspondant (pour pouvoir interrompre la répétition le moment venu.
const intervalId = scroll ? setInterval(scrollStep, delayInMs) : undefined;
Il ne reste plus qu’à terminer le JSX du composant en ajoutant le déclenchement du changement de state lorsque le scroll n’est pas actif et que le bouton reçoit un événement onClick.
<button className="btn btn-secondary scrollToTop" onClick={e => scroll || setScroll(true)}>
<span className="glyphicon glyphicon-chevron-up"/>
</button>
Et voici le résultat :
See the Pen ScrollToTop Button with ReactJS by Frédéric MISERY (@FredM) on CodePen.